from lib.net.index import wlan
from lib.mqtt.index import client
from lib.clock import ticker_clock
from lib.config.index import mqtt_config, device_config
from utils.tuya import generate_username, generate_password, generate_clientID, generate_msg
from utils.common import print_gc_info, collect_gc, unix_time
from utils.device import get_info, get_id
from lib.board.led.index import led
from lib.board.ws2812 import WS2812
import asyncio
import json
import sys

ProductID = device_config.get_custom_value("ProductID")
DeviceID = device_config.get_custom_value("DeviceID")
DeviceSecret = device_config.get_custom_value("DeviceSecret")

if not ProductID:
    print("no ProductID")
    sys.exit()

if not DeviceID:
    print("no DeviceID")
    sys.exit()

if not DeviceSecret:
    print("no DeviceSecret")
    sys.exit()

propertySetTopic = f"tylink/{DeviceID}/thing/property/set"
propertyReportTopic = f"tylink/{DeviceID}/thing/property/report"

__service__ = "tuya_client"
__description__ = "tuya mqtt client sub and pub"

keep_alive = mqtt_config.get_keepalive()

kp = max(keep_alive if isinstance(keep_alive, (int)) else 55, 55)

timer = ticker_clock.TickerClock(kp * 1000)
is_debug = mqtt_config.is_debug()

ws2812_led = WS2812(1, 10)
ws2812_led.clear()

device_fields = {
    "lamp_switch": False,
    "pickup_angle": 0,
    "ws2812_switch": False,
    "ws2812_mode": "rainbow",  # rainbow, rolling
    "ws2812_num": 10
}


def handle_lamp_switch():
    if device_fields["lamp_switch"]:
        led.on()
    else:
        led.off()


async def handle_ws2812_switch():
    global ws2812_led
    print("ws2812", device_fields["ws2812_switch"], device_fields["ws2812_mode"])
    if device_fields["ws2812_switch"]:
        if device_fields["ws2812_mode"] == "rainbow":
            ws2812_led.start("rainbow")
        if device_fields["ws2812_mode"] == "rolling":
            ws2812_led.start("rolling")
    else:
        ws2812_led.stop()
        ws2812_led.clear()

def handle_ws2812_num(fields):
    global ws2812_led
    if "ws2812_num" in fields:
        print("handle set ws2812_num: ", fields["ws2812_num"])
        ws2812_led.set_num(fields["ws2812_num"])


def property_set_handler(topic, json_msg):
    print("handle property set: ", json_msg)
    time = json_msg.get("time")
    msgId = json_msg.get("msgId")
    data = json_msg.get("data", {})

    for key in device_fields.keys():
        if key in data:
            device_fields[key] = data[key]

    print("updated device_fields:", device_fields)

    handle_lamp_switch()
    handle_ws2812_num(device_fields)
    asyncio.create_task(handle_ws2812_switch())
    # after update, upload info
    report_info()


def callback(topic_bytes, msg_bytes):
    topic = topic_bytes.decode('utf-8')
    msg = msg_bytes.decode('utf-8')
    # print("handle msg: ", topic, msg)
    json_msg = json.loads(msg)
    if topic == propertySetTopic:
        property_set_handler(topic, json_msg)


def report_info():
    global client
    time = unix_time()
    data = {
        "mcu_info": {
            "time": time,
            "value": str(get_info()["uname"]["machine"])
        },
        "device_status": {
            "time": time,
            "value": str(get_info()["ifconfig"]["ip"])
        },
        "inverter_id": {
            "time": time,
            "value": get_id()
        },
        "lamp_switch": {
            "time": time,
            "value": device_fields["lamp_switch"]
        },
        "last_online_time": {
            "time": time,
            "value": time/1000
        }
    }
    for key, value in device_fields.items():
        data[key] = {
            "time": time,
            "value": value
        }
    client.publish(generate_msg(data), propertyReportTopic)


def keepalive_timer():
    global client
    # if is_debug:
    #     print("mqtt ping diff: ", timer.get_diff())
    if timer.check():
        if is_debug:
            print("mqtt publish ping")
        client.ping()

        # 上报设备信息
        report_info()


def init():
    global client
    wlan.connect()
    client.set_callback(callback)
    print_gc_info()
    collect_gc()
    client.connect(generate_clientID(DeviceID), generate_username(DeviceID), generate_password(DeviceID, DeviceSecret))
    client.subscribeTopic(propertySetTopic)
    report_info()


async def run():
    while True:
        keepalive_timer()
        await client.wait_msg()
        await asyncio.sleep(1)


if __name__ == "__main__":
    client.connect(generate_clientID(DeviceID), generate_username(DeviceID), generate_password(DeviceID, DeviceSecret))

